package com.xishu.foodpanda;

import com.xishu.config.Constant;
import com.xishu.dao.jpa.ProductDao;
import com.xishu.entity.foodpanda.Category;
import com.xishu.entity.foodpanda.Menu;
import com.xishu.entity.foodpanda.Product;
import com.xishu.entity.shop.Catalog;
import com.xishu.entity.shop.Item;
import com.xishu.entity.shop.PayType;
import com.xishu.entity.shop.Shop;
import com.xishu.response.VerifyUtil;
import com.xishu.service.*;
import com.xishu.util.BeanUtil;
import com.xishu.util.Tools;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

import static com.xishu.config.Constant.ORDER_PAY_TYPE_CASH;
import static com.xishu.response.ResponseStatus.SYSTEM_BUSY;

public class FoodPandaConfigService implements Tools {
    private static Logger logger = LoggerFactory.getLogger(FoodPandaConfigService.class);
    private static FoodPandaConfigService instance = new FoodPandaConfigService();
    private CommonService commonService = CommonService.getInstance();

    private FoodPandaConfigService() {
    }

    public static FoodPandaConfigService getInstance() {
        return instance;
    }

    /**
     * 查询相同类型下面的菜单
     *
     * @param shopId
     * @param menuType
     * @return
     */
    public List<Menu> findMenuList(Long shopId, Integer menuType) {
        Menu menu = new Menu();
        menu.setShopId(shopId);
        menu.setMenuType(menuType);
        menu.setEntity(true);

        return commonService.searchAll(menu);
    }

    /**
     * 查询分店下面的菜单列表
     *
     * @param shopId
     * @return
     */
    public List<Menu> findMenuList(Long shopId) {
        Menu menu = new Menu();
        menu.setShopId(shopId);
        menu.setEntity(true);

        return commonService.searchAll(menu);
    }

    /**
     * 通过ID查询菜的列表
     *
     * @param id
     * @return
     * @throws Exception
     */
    public Menu findMenuById(Long id) throws Exception {
        Menu menu = new Menu();
        menu.setId(id);
        return commonService.findEntity(menu, true);
    }

    /**
     * 通过ID来查询Category
     *
     * @param id
     * @return
     */
    public Category findCategoryById(Long id) throws Exception {
        Category category = new Category();
        category.setId(id);
        return commonService.findEntity(category, true);
    }

    /**
     * 对category重新排序
     *
     * @param category
     */
    public void sortCategory(Category category) throws Exception {
        commonService.modifyShowOrder(category, ShopService.getInstance().findEntityListByShopId(category.getShopId(), Category.class));
    }

    /**
     * 将dola的菜转化成foodpanda的菜
     *
     * @return
     */
    public Product itemToProduct(Item item) {
        Product product = new Product();
        BeanUtils.copyProperties(item, product);

        product.setBelongToItemId(item.getId());
        product.setId(null);
        product.setRequestId(null);
        product.setCreateTime(System.currentTimeMillis());
        return product;
    }

    /**
     * 查询Product
     *
     * @param categoryId
     * @param itemId
     * @return
     */
    public Product findProduct(Long categoryId, Long itemId) {
        Product product = new Product();
        product.setBelongToItemId(itemId);
        product.setCategoryId(categoryId);
        product.setEntity(true);
        return commonService.searchOne(product);
    }

    /**
     * 通过ID去查询Product
     *
     * @param productId
     * @return
     */
    public Product findProductById(Long productId) throws Exception {
        Product product = new Product();
        product.setId(productId);
        return commonService.findEntity(product, true);
    }

    /**
     * 通过CategoryID来查询
     *
     * @param categoryId
     * @return
     */
    public List<Product> findProductListByCategoryId(Long categoryId) {
        Product product = new Product();
        product.setCategoryId(categoryId);
        product.setEntity(true);
        return commonService.searchAll(product);
    }

    /**
     * 过滤掉已经导入的菜，剩下的菜都是没有导入过的
     *
     * @param ids
     * @return
     */
    public List<Long> filterImportedItem(Long categoryId, List<Long> ids) {
        return ids.stream().filter(id -> {
            Product product = findProduct(categoryId, id);
            return product == null;
        }).collect(Collectors.toList());
    }

    /**
     * 获取某一个category下面的最大排序值
     *
     * @param categoryId
     * @return
     */
    public int findMaxShowOrderInCategory(Long categoryId) {
        ProductDao productDao = BeanUtil.getBean(ProductDao.class);
        return getInt(productDao.maxShowOrder(categoryId));
    }

    /**
     * 对菜品排序
     * <p>
     * 先按照品类排序，然后按照品类下面的菜来排序
     *
     * @param itemList
     * @return
     */
    public List<Item> sortItem(List<Item> itemList) {
        CatalogService catalogService = CatalogService.getInstance();
        return itemList.stream().sorted(new Comparator<Item>() {
            @Override
            public int compare(Item o1, Item o2) {
                try {
                    Catalog catalog1 = catalogService.findCatalogById(o1.getCatalogId());
                    Catalog catalog2 = catalogService.findCatalogById(o2.getCatalogId());
                    if (catalog1.getShowOrder() < catalog2.getShowOrder()) {
                        return -1;
                    } else if (catalog1.getShowOrder() > catalog2.getShowOrder()) {
                        return 1;
                    } else {
                        //相同的catalog,比较菜的顺序
                        return o1.getShowOrder() - o2.getShowOrder();
                    }
                } catch (Exception e) {
                    logger.error("e", e);
                    return 0;
                }
            }
        }).collect(Collectors.toList());
    }

    /**
     * 查询foodPanda支付方式
     *
     * @param shopId
     * @return
     */
    public PayType findFoodPandaPayType(Long shopId) {
        PayType payType = new PayType();
        payType.setEntity(true);
        payType.setShopId(shopId);
        payType.setName_zh("FoodPanda");
        payType.setName_en("FoodPanda");
        payType.setDefaultType(true);
        return commonService.searchOne(payType);
    }

    /**
     * 给分店添加foodPanda支付方式
     *
     * @param shopId
     */
    public void addFoodPandaPayType(Long shopId) throws Exception {
        PayType foodPandaPayType = findFoodPandaPayType(shopId);

        if (foodPandaPayType != null) {
            logger.info("already has food panda pay type");
            return;
        }

        logger.info("will create food panda pay type");

        Shop shop = ShopService.getInstance().findShopById(shopId);

        //查询现有的最大的payType,然后加1变成food panda的pay Type
        PayTypeService payTypeService = PayTypeService.getInstance();
        int maxPayType = payTypeService.maxPayType(shopId);
        //至少有现金支付，提示信息后面再换
        VerifyUtil.verify(() -> maxPayType >= ORDER_PAY_TYPE_CASH, SYSTEM_BUSY);

        //图票暂时没有
        payTypeService.createDefaultPayType(shopId, shop, Constant.FOOD_PANDA, Constant.FOOD_PANDA, maxPayType + 1, "us_cash.png", true);
    }

    /**
     * 是否可以删除品类
     * 一个都没有的时候，可以删除
     *
     * @param categoryId
     * @return
     */
    public boolean canDeleteCategory(Long categoryId) {
        Product product = new Product();
        product.setCategoryId(categoryId);
        return commonService.searchOne(product) == null;
    }

    /**
     * 获取所有的菜的ID，ID为DOLA主系统的菜
     *
     * @param product
     * @return
     */
    public List<Long> getAllItemIdList(Product product) {
        List<Long> idList = new ArrayList<>();

        idList.add(product.getBelongToItemId());

        if (!getBoolean(product.getSetMenu())) {
            logger.info("normal item");
            return idList;
        }

        idList.addAll(product.getSetMenuOneItemList().stream().flatMap(setMenuOneItem -> getList(setMenuOneItem.getItemList()).stream()).map(item -> item.getId()).collect(Collectors.toList()));

        return idList;
    }

    /**
     * 获取所有跟菜相关的Item级别的Product
     * <p>
     * ITEM级别包含Product本身，以及套餐里面的固定菜
     *
     * @param itemId
     * @return
     */
    public List<Product> getAllItemLevelProduct(Long itemId) throws Exception {
        Item item = ItemService.getInstance().findItem(itemId);
        List<Product> itemLevelProductList = new ArrayList<>();

        List<Product> productList = findProductListByShopId(item.getShopId());

        itemLevelProductList.addAll(productList.stream().filter(product -> equals(product.getBelongToItemId(), itemId)).collect(Collectors.toList()));
        itemLevelProductList.addAll(productList.stream().filter(product -> !equals(product.getBelongToItemId(), itemId)).filter(product -> getBoolean(product.getSetMenu())).filter(product -> {
            return product.getSetMenuOneItemList().stream().filter(setMenuOneItem -> getBoolean(setMenuOneItem.getFixed())).filter(setMenuOneItem -> {
                return setMenuOneItem.getItemList().stream().filter(itemTmp -> equals(itemTmp.getId(), itemId)).findAny().isPresent();
            }).findAny().isPresent();
        }).collect(Collectors.toList()));

        return itemLevelProductList;
    }

    /**
     * 获取所有跟菜相关的Topping级别的Product
     * <p>
     * 套餐里面的可选菜
     *
     * @param itemId
     * @return
     */
    public List<Product> getAllToppingLevelProduct(Long itemId) throws Exception {
        Item item = ItemService.getInstance().findItem(itemId);
        List<Product> itemLevelProductList = new ArrayList<>();

        List<Product> productList = findProductListByShopId(item.getShopId());

        itemLevelProductList.addAll(productList.stream().filter(product -> !equals(product.getBelongToItemId(), itemId)).filter(product -> getBoolean(product.getSetMenu())).filter(product -> {
            return product.getSetMenuOneItemList().stream().filter(setMenuOneItem -> !getBoolean(setMenuOneItem.getFixed())).filter(setMenuOneItem -> {
                return setMenuOneItem.getItemList().stream().filter(itemTmp -> equals(itemTmp.getId(), itemId)).findAny().isPresent();
            }).findAny().isPresent();
        }).collect(Collectors.toList()));

        return itemLevelProductList;
    }

    /**
     * 过滤一个套餐里面的一个菜
     *
     * @param product
     * @param itemId
     * @return
     */
    public List<Item> filterItemInSetMenu(Product product, Long itemId) {
        return product.getSetMenuOneItemList().stream().flatMap(setMenuOneItem -> getList(setMenuOneItem.getItemList()).stream()).filter(item -> {
            return equals(item.getId(), itemId);
        }).collect(Collectors.toList());
    }

    public List<Product> findProductListByShopId(Long shopId) {
        Product product = new Product();
        product.setShopId(shopId);
        return commonService.searchAll(product);
    }

}
